package system.train;

import java.util.LinkedList;
import java.util.Queue;
import system.track.Block;
import system.track.Switch;
import system.track.Direction;
import system.track.SwitchAngle;
import system.track.Sensor;
import system.track.IllegalFunctionCallException;

/**
 * The Route determines the set of actions that a ConcreteTrain will
 * perform.  For Cycle 1, the demo route is pre-programmed dependent
 * upon a single variable; the Direction the train is pointed.
 * 
 * @author Yasmine Kandissounon
 * @version Cycle 1 - complete
 */
public class Route
{
    // all orders for the train are stored in a queue
    private Queue<RouteActions> queue;
    // initial direction of the train, clockwise or counter
    private Direction direction;

    /**
     * Constructor for Objects of class Route.
     * 
     * @param queue a Queue of RouteActions containing a list
     * of instructions for this particular Route
     */
    private Route(Queue<RouteActions> queue)
    {
        this.queue = queue;
    }

    /**
     * Creates a Route based upon a single Direction variable.
     * 
     * @param direction a Direction that initializes the Route; this is
     * either clockwise or counterclockwise
     */
    public static Route createRoute(Direction direction)
    {
        Queue<RouteActions> thequeue = new LinkedList<RouteActions>();
        switch(direction)
        {
            case CLOCKWISE:
            {   
                    // First outer loop
                    //Starting on Block 1
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.ACTIVATE_CURRENT_BLOCK);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 9
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    
                    // ON BLOCK 8
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //SECOND OUTER
                    // ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 9
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 8
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //FIRST INNER LOOP
                    // ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 7
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 6
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // SECOND INNER LOOP
                    // ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 7
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    // ON BLOCK 6
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //CROSSOVER
                    // ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_PARKING_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 4
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.TOGGLE_DIRECTION);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 7
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //FIRST INNER CCW
                    //ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 6
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 7
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //SECOND INNER CCW
                    //ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 6
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 7
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_90);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //FIRST OUTER CCW
                    //ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 8
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 9
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //SECOND OUTER CCW
                    //ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 1
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 8
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 9
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //ON BLOCK 2
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.SET_NEXT_SWITCH_180);
                    thequeue.offer(RouteActions.ACTIVATE_NEXT_BLOCK);
                    thequeue.offer(RouteActions.REGISTER_SENSORS);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);

                    //on block 1 end
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS);
                    thequeue.offer(RouteActions.DEACTIVATE_PREVIOUS_BLOCK);
                    thequeue.offer(RouteActions.MOVE_TRAIN_AHEAD);
                    thequeue.offer(RouteActions.STOP);
                    thequeue.offer(RouteActions.TOGGLE_DIRECTION);
                return new Route(thequeue);
            }
            case COUNTERCLOCKWISE:
            { // per the demo for cycle 1, these instructions were omitted
                // First outer loop    
                    /*thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    // Second outer loop
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    // First inner loop
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_90);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_90);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    // Second inner loop
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_90);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_180);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);
                    
                    thequeue.offer(RouteActions.REGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.SET_SWITCH_COUNTERCLOCKWISE_90);
                    thequeue.offer(RouteActions.WAIT_FOR_SENSOR);
                    thequeue.offer(RouteActions.UNREGISTER_SENSORS_COUNTERCLOCKWISE);
                    thequeue.offer(RouteActions.ACTIVATE_BLOCK_COUNTERCLOCKWISE);*/
                return new Route(thequeue);
            }
            default:
                throw new IllegalArgumentException("Bad direction arg.");
        }
    }

    /**
     * Executes the next action in the Route.
     * 
     * @param train a Train executing the action
     * @return  a boolean that will return false unless the train is
     * waiting for a Sensor to trip
     */
    public boolean executeNextAction(Train train)
    {
       RouteActions action = queue.poll();
       boolean returnVal = action.executeAction(train);
       queue.offer(action);
       return returnVal;
    }
}
